#!python
""" pbfi.py
Tool to inspect binary files
"""
__version__ = "0.1 alpha"

import pbfi_model_parser

import sys
import struct
import util

class BrickReader:
    def __init__(self, context, fd, blocks):
        self.context = context
        self.blocks = []
        self.fd = fd
    
    def suffix_traverse(self, brick):
        pass

    def prefix_traverse(self, brick):
        format = brick.reader_format()
        if format != None:
            size = struct.calcsize(str(format))
            bytes = self.fd.read(size)
            value = struct.unpack(str(format), bytes)[0]
                    
            block = {	
                    'format':brick.type, 
                    'name':brick.name,
                    'value':value, 
                    }
            
            self.context[str(brick.id)] = value
            self.blocks.append(block) 

class BinaryFileInspector(util.Observer,util.Subject):
    def __init__(self):
        util.Subject.__init__(self)
        self.blocks = None
        self.structure = None
        self.context = None
        self.binary_filename = None
        self.model_filename = None

    def load_model(self,model_filename):
        self.model_filename = model_filename
        self.reload_model()

    def reload_model(self):
        (self.structure,self.context) = pbfi_model_parser.parse(self.model_filename)
        self.notify()

    def load(self,binary_filename):
        self.binary_filename = binary_filename
        self.reload()

    def reload(self):
        fileobj = open(self.binary_filename, mode='rb') 
        self.blocks = []
        br = BrickReader(self.context, fileobj, self.blocks)
        self.structure.traverse(br)
        self.blocks = br.blocks
        self.context = br.context
        fileobj.close()
        self.notify()

    def update(self):
        self.notify()

def display_blocks(blocks):
    """
    Simple display function
    """
    for block in blocks:
        print block['name'], block['value']

def main(argv=None):
    """
    Inspect a binary file (second argument) according to the model file (first argument)
    then do a dummy display of the result
    """
    bfi = BinaryFileInspector()
    bfi.load_model(sys.argv[1])
    bfi.load(sys.argv[2])
    blocks = bfi.blocks 
    display_blocks(blocks)

if __name__ == "__main__":
    main()

